package com.jhj.service.bm.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.github.pagehelper.PageHelper;
import com.jhj.po.bm.mapper.SaleMapper;
import com.jhj.po.bm.model.BmOrder;
import com.jhj.po.bm.model.Sale;
import com.jhj.vo.bm.ChartSearchVo;
import com.jhj.vo.bm.OrderSearchVo;
import com.jhj.vo.bm.SaleStatVo;
import com.jhj.vo.bm.SaleVo;
import com.jhj.service.bm.BmOrderService;
import com.jhj.service.bm.OrderContractService;
import com.jhj.service.bm.SaleService;
import com.jhj.service.impl.BaseServiceImpl;
import com.jhj.utils.BeanUtilsExp;
import com.jhj.utils.BmUtil;
import com.jhj.utils.Constants;
import com.jhj.utils.DateUtil;
import com.jhj.utils.StringUtil;
import com.jhj.utils.TimeStampUtil;

import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

@Service
public class SaleServiceImpl extends BaseServiceImpl<Sale> implements SaleService {
	
	@Autowired
	private SaleMapper saleMapper;
	
	@Autowired
	private BmOrderService orderService;

	@Autowired
	private OrderContractService orderContractService;

	/**
	 * 保姆订单派工逻辑 1. 特殊情况 1.1 用户先找出上一单签约成功的分配老师，直接分配, 分配依据：老客户 1.2 老师自己下的单，直接分配给这个老师 1.3
	 * 老师分享出去的，用户在小程序直接预约，也会分配给他 2. 如果没有1的情况，则进入正常的排单规则 逻辑判断 2.1
	 * 先查询用户第一单对应的老师ID，如果此老师为在职，则直接选择此老师，如果为离职往下继续 2.2 先查 sale.leve = 1 ，得到集合A 2.3
	 * 统计集合A每个sale id 的当前订单数，就是 order_status > 0 and order_status <4 ，排除饱和量后得到集合B
	 * 2.4 集合B随机得到一个。 2.5 找到匹配的sale_id 之后，更新 order表 。 3. 额外订单排单规则， 一般用于前2个步骤都已经满了的情况
	 * 3.1 额外订单数 = 总订单数（进行中的订单，未关闭和未签约的订单） - 系统派单饱和量 3.2 找出额外订单数最小的进行派工
	 * 
	 * @param saleId
	 *            销售老师Id
	 * @param saleMobile
	 *            销售老师手机号
	 * @param orderId
	 *            订单ID
	 * @param addFrom
	 *            订单来源 0 = 用户下单 1 = 客服 2 = 销售老师下单
	 * 
	 * @return saleId 派单老师ID dispatchBy 派单依据 orderDispatch 0 = 系统派单 1 = 自主开发
	 * 
	 */
	@Override
	public HashMap<String, Object> orderDispatch(Integer saleId, String saleMobile, Integer orderId, Integer addFrom) {

		HashMap<String, Object> dispatchInfo = null;
		Sale searchSale = null;
		Sale sale = null;

		// ================1.2 老师自己下的单，直接分配给这个老师
		// ================1.3 老师分享出去的，用户在小程序直接预约，也会分配给他
		if (saleId != null && saleId > 0) {
			dispatchInfo = new HashMap<String, Object>();
			dispatchInfo.put("saleId", saleId);
			if (addFrom == 0) {
				dispatchInfo.put("dispatchBy", "分享预约");
			} else {
				dispatchInfo.put("dispatchBy", "自有客户");
			}
			dispatchInfo.put("orderDispatch", 1);

			return dispatchInfo;
		}

		if (!StringUtil.isEmpty(saleMobile)) {
			dispatchInfo = new HashMap<String, Object>();
			searchSale = new Sale();
			sale.setMobile(saleMobile);
			sale = this.selectOne(searchSale);
			dispatchInfo.put("saleId", sale.getSaleId());
			if (addFrom == 0) {
				dispatchInfo.put("dispatchBy", "分享预约");
			} else {
				dispatchInfo.put("dispatchBy", "自有客户");
			}
			dispatchInfo.put("orderDispatch", 1);
			return dispatchInfo;
		}
		return dispatchInfo;
//		dispatchInfo.put("orderDispatch", 0);
//		// ================1.1 用户先找出上一单预约成功的分配老师，直接分配, 分配依据：老客户
//		Integer userId = order.getUserId();
//		BmOrder b = new BmOrder();
//		b.setUserId(userId);
//		b.setOrderStatus(Constants.ORDER_STATUS_4);
//		List<BmOrder> historyOrderList = orderService.selectBySearchVo(b, "add_time desc");
//		if (!historyOrderList.isEmpty()) {
//			for (BmOrder historyOrder : historyOrderList) {
//				if (historyOrder != null) {
//					if (historyOrder.getSaleId() != null && historyOrder.getSaleId() > 0) {
//						dispatchInfo.put("saleId", historyOrder.getSaleId());
//						dispatchInfo.put("dispatchBy", "老客户");
//						return dispatchInfo;
//					}
//				}
//			}
//		}
//
//	// ================2. 如果没有1的情况，则进入正常的排单规则
//	List<SaleStatVo> list = this.getSaleStatVos();
//	Sale dispatchSale = this.orderDispatchByOrderCount(list);
//	if(dispatchSale!=null) {
//		dispatchInfo.put("saleId", dispatchSale.getSaleId());
//		dispatchInfo.put("dispatchBy", "签约数优先");
//		return dispatchInfo;
//	}
//
//	// ================3. 额外订单排单规则， 一般用于前2个步骤都已经满了的情况
//	if(dispatchSale==null)
//	{
//		
//		String[] sortNameArr = { "totalProcess" };
//		boolean[] typeArr = { true };
//		ListUtil.sort(list, sortNameArr, typeArr);
//		dispatchSale = list.get(0);
//		dispatchInfo.put("saleId", dispatchSale.getSaleId());
//		dispatchInfo.put("dispatchBy", "订单数最少");
//		return dispatchInfo;
//	}

//	return dispatchInfo;
	}

	/**
	 * 2. 如果没有1的情况，则进入正常的排单规则 逻辑判断 2.1 先查询用户第一单对应的老师ID，如果此老师为在职，则直接选择此老师，如果为离职往下继续
	 * 2.2 先查 sale.leve = 1 ，得到集合A 2.3 统计集合A每个sale id 的当前订单数，就是 order_status > 0 and
	 * order_status <4 ，排除饱和量后得到集合B 2.4 集合B随机得到一个。 2.5 找到匹配的sale_id 之后，更新 order表 。。
	 * 
	 * @return Sale
	 */
	private Sale orderDispatchByOrderCount(List<SaleStatVo> list) {
		Sale dispatchSale = null;
		
		List<SaleStatVo> canDispatchList = new ArrayList<SaleStatVo>();
		int level = 1;
		while (level <= 4) {
			canDispatchList = this.findUnFullOrderByLeavel(list, level);
			if (!canDispatchList.isEmpty())
				break;
			level++;
		}

		if (!canDispatchList.isEmpty()) {
			// 随机打乱
			Collections.shuffle(canDispatchList);

			// 再随机取值.
			Random rand = new Random();
			int randIndex = rand.nextInt(canDispatchList.size());
			dispatchSale = canDispatchList.get(randIndex);
			return dispatchSale;
		}

		return dispatchSale;
	}

	@SuppressWarnings("unlikely-arg-type")
	private List<SaleStatVo> getSaleStatVos() {
		List<SaleStatVo> list = new ArrayList<SaleStatVo>();

		Sale saleSearchVo = new Sale();
		saleSearchVo.setStatus(1);
		List<Sale> saleList = mapper.select(saleSearchVo);

		// 获取销售老师订单数
		OrderSearchVo orderVo = new OrderSearchVo();
		List<Map<Integer, Integer>> countSaleList = orderService.countOrderSale(orderVo);

		// 获取销售老师总金额数
//		ChartSearchVo chartSearchVo = new ChartSearchVo();
//		List<Map<Integer, BigDecimal>> sumSaleList = orderContractService.sumSaleOrderPay(chartSearchVo);

		int saleLen = saleList.size();

		for (int i = 0; i < saleLen; i++) {
			Sale sale = saleList.get(i);
			Integer saleId = sale.getSaleId();
			Integer level = sale.getLevel();
			Integer fullOrderNum = BmUtil.getLeveFullOrder(level);
			SaleStatVo saleStatVo = new SaleStatVo();
			BeanUtilsExp.copyPropertiesIgnoreNull(sale, saleStatVo);
			saleStatVo.setTotal(0);
			saleStatVo.setTotalProcess(0);
			saleStatVo.setTotalDone(0);
			saleStatVo.setTotalOrderPay(new BigDecimal(0));
			saleStatVo.setTotalExtra(0);
			// 找出订单总数
			int countSaleLen = countSaleList.size();
			for (int j = 0; j < countSaleLen; j++) {
				Map<Integer, Integer> item = countSaleList.get(j);
				Integer countSaleId = item.get("saleId").intValue();
				Integer total = ( (Number)item.get("total") ).intValue();
				Integer totalProcess =  ( (Number) item.get("totalProcess") ).intValue();
				Integer totalDone =  ( (Number) item.get("totalDone") ).intValue();
				if (countSaleId.equals(saleId)) {
					saleStatVo.setTotal(total);
					saleStatVo.setTotalProcess(totalProcess);
					saleStatVo.setTotalDone(totalDone);
					if (totalProcess > fullOrderNum) {
						saleStatVo.setTotalExtra(totalProcess - fullOrderNum);
					}
					break;
				}
			}
			list.add(saleStatVo);
		}

		return list;
	}

	private List<SaleStatVo> findUnFullOrderByLeavel(List<SaleStatVo> list, Integer level) {
		List<SaleStatVo> result = new ArrayList<SaleStatVo>();
		Integer fullOrderNum = BmUtil.getLeveFullOrder(level);
		int len = list.size();
		for (int i = 0; i < len; i++) {
			SaleStatVo vo = list.get(i);
			if (vo.getLevel().equals(level)) {
				Integer totalProcess = vo.getTotalProcess();
				if (totalProcess < fullOrderNum) {
					result.add(vo);
				}
			}
		}
		return result;
	}

	@Override
	public List<Sale> selectByListPage(SaleVo vo, Integer pageNo, Integer pageSize, String orderBy) {
		PageHelper.startPage(pageNo, pageSize);
		
		if (!StringUtil.isEmpty(orderBy)) vo.setOrderBy(orderBy);

		return saleMapper.selectByListPage(vo);
	}
	
	
	@Override
	public List<Sale> selectBySearchVo(SaleVo vo, String orderBy) {
		
		if (!StringUtil.isEmpty(orderBy)) vo.setOrderBy(orderBy);

		return saleMapper.selectBySearchVo(vo);
	}
	
	
	private Example getSearchVoExample(SaleVo vo) {
		Example example = new Example(Sale.class);
		Criteria createCriteria = example.createCriteria();

		if (vo.getName() != null && !"".equals(vo.getName())) {
			createCriteria.andCondition("name = '" + vo.getName() + "'");
		}

		if (vo.getMobile() != null && !"".equals(vo.getMobile())) {
			createCriteria.andCondition("instr(" + vo.getMobile() + ",mobile)");
		}

		if (vo.getLevels() != null && !"".equals(vo.getLevels())) {
			createCriteria.andCondition("level in (" + vo.getLevels() + ")");
		}

		if (vo.getStartTimeStr() != null && !"".equals(vo.getStartTimeStr())) {
			Long startTime = TimeStampUtil.getMillisOfDayFull(vo.getStartTimeStr() + " 00:00:00") / 1000;
			createCriteria.andCondition("add_time >=" + startTime.intValue());
		}
		if (vo.getEndTimeStr() != null && !"".equals(vo.getEndTimeStr())) {
			Long endTime = TimeStampUtil.getMillisOfDayFull(vo.getEndTimeStr() + " 00:00:00") / 1000;
			createCriteria.andCondition("add_time <=" + endTime);
		}
		if (vo.getStatus() != null) {
			createCriteria.andCondition("status =" + vo.getStatus());
		}
		return example;
	}

	/**
	 * 销售老师分配的未完成订单数量
	 */
	public Map<String, Integer> saleAndOrder(List<Sale> saleList, List<BmOrder> orderList) {
		Map<String, Integer> map = new HashMap<>();

		for (Sale s : saleList) {
			Integer saleId = s.getSaleId();
			Integer count = 0;
			for (BmOrder o : orderList) {
				if (saleId == o.getSaleId()) {
					count++;
				}
			}
			if (s.getLevel() == 1) {
				count = count - 4;
			}
			if (s.getLevel() == 2) {
				count = count - 3;
			}
			if (s.getLevel() == 3) {
				count = count - 2;
			}
			if (s.getLevel() == 4) {
				count = count - 1;
			}
			map.put(String.valueOf(saleId), count);
		}
		return map;
	}

	/**
	 * 判断销售老师级别, 金额为三个月内的总金额数.
	 * 
	 */
	@Override
	public int getSaleLevel(Integer saleId) {
		Integer level = Constants.LEVEL_4;

		ChartSearchVo searchVo = new ChartSearchVo();
		searchVo.setSaleId(saleId);

		Date nowDate = DateUtil.getNowOfDate();
		// 最近三个月数据
		Calendar cal = Calendar.getInstance();
		cal.setTime(nowDate);
		cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) - 3);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		Long startDate = TimeStampUtil.getMillisOfDay(DateUtil.formatDate(cal.getTime())) / 1000;

		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(nowDate);
		cal1.set(Calendar.MONTH, cal1.get(Calendar.MONTH));
		cal1.set(Calendar.DAY_OF_MONTH, 0);
		Long endDate = TimeStampUtil.getMillisOfDay(DateUtil.formatDate(cal1.getTime())) / 1000;

		searchVo.setStartTime(startDate.intValue());
		searchVo.setEndTime(endDate.intValue());

		List<Map<Integer, BigDecimal>> sumSaleList = orderContractService.sumSaleOrderPay(searchVo);

		if (sumSaleList == null || sumSaleList.isEmpty())
			return level;
		Map<Integer, BigDecimal> item = sumSaleList.get(0);
		BigDecimal totalPay = new BigDecimal(item.get("totalPay").toString());

		if (totalPay.compareTo(Constants.LEVEL_VALUE_3) == -1) {
			level = Constants.LEVEL_4;
		}
		if (totalPay.compareTo(Constants.LEVEL_VALUE_3) >= 0 && totalPay.compareTo(Constants.LEVEL_VALUE_2) == -1) {
			level = Constants.LEVEL_3;
		}
		if (totalPay.compareTo(Constants.LEVEL_VALUE_2) >= 0 && totalPay.compareTo(Constants.LEVEL_VALUE_1) == -1) {
			level = Constants.LEVEL_2;
		}
		if (totalPay.compareTo(Constants.LEVEL_VALUE_1) >= 0) {
			level = Constants.LEVEL_1;
		}

		return level;
	}

}
